using System.Collections.Generic;
using System;
using UnityEngine;
using YooAsset;
using Cysharp.Threading.Tasks;

namespace LFramework 
{
    /// <summary>
    /// 资源 管理器
    /// </summary>
    public class AssetsManager : IDisposable
    {
        private Dictionary<string, AssetRefEntity> m_AssetRefEntityDic = new Dictionary<string, AssetRefEntity>();
        //等待卸载资源路径
        private List<string> m_RemoveUnloadAssetList = new List<string>();

        /// <summary>
        /// 异步加载资源，通过回调的方式
        /// </summary>
        /// <param name="assetFullPath"></param>
        /// <param name="loadCompleteCB"></param>
        public void LoadAssetAsync(string assetFullPath ,Action<string,UnityEngine.Object> loadCompleteCB)
        {
            if (!m_AssetRefEntityDic.TryGetValue(assetFullPath, out AssetRefEntity refEntity)) 
            {
                refEntity = AssetRefEntity.Create(assetFullPath);
                m_AssetRefEntityDic.Add(assetFullPath, refEntity);
            }
            refEntity.ReferenceAdd();
            refEntity.LoadAssetAsync(loadCompleteCB);
        }

        /// <summary>
        /// 异步卸载资源
        /// </summary>
        /// <param name="assetFullPath"></param>
        /// <param name="loadCompleteCB"></param>
        public void UnLoadAssetAsync(string assetFullPath, Action<string,UnityEngine.Object> loadCompleteCB)
        {
            if (m_AssetRefEntityDic.TryGetValue(assetFullPath, out AssetRefEntity refEntity)) 
            {
                refEntity.UnloadAssetAsync(loadCompleteCB);
                refEntity.ReferenceRemove();
            }
            else
                GameEntry.Log("卸载资源失败，未找到资源 path:", assetFullPath);
        }

        /// <summary>
        /// 异步加载资源，通过UniTask方式
        /// </summary>
        public async UniTask<T> LoadAssetAsync<T>(string assetFullPath) where T : UnityEngine.Object
        {
            if (!m_AssetRefEntityDic.TryGetValue(assetFullPath, out AssetRefEntity refEntity))
            {
                refEntity = AssetRefEntity.Create(assetFullPath);
                m_AssetRefEntityDic.Add(assetFullPath, refEntity);
            }
            refEntity.ReferenceAdd();
            return await refEntity.LoadAssetAsync<T>();
        }

        /// <summary>
        /// 同步加载
        /// </summary>
        public T LoadAssetSync<T>(string assetFullPath) where T : UnityEngine.Object
        {
            if (!m_AssetRefEntityDic.TryGetValue(assetFullPath, out AssetRefEntity refEntity))
            {
                refEntity = AssetRefEntity.Create(assetFullPath);
                m_AssetRefEntityDic.Add(assetFullPath, refEntity);
            }
            refEntity.ReferenceAdd();
            return refEntity.LoadAssetSync<T>();
        }

        /// <summary>
        /// 同步卸载 资源
        /// </summary>
        public void UnLoadAssetSync(string assetFullPath)
        {
            if (m_AssetRefEntityDic.TryGetValue(assetFullPath, out AssetRefEntity refEntity))
                refEntity.ReferenceRemove();
            else
                GameEntry.Log("卸载资源失败，未找到资源 path:", assetFullPath);
        }

        public void OnUpdata() 
        {
            CheckAssetRelease();
        }

        /// <summary>
        /// 检查是否有可卸载的资源
        /// </summary>
        private void CheckAssetRelease() 
        {
            //释放 不用的 asset
            foreach (var item in m_AssetRefEntityDic)
            {
                if (item.Value.GetCanRelease()) 
                {
                    //释放对象池
                    GameEntry.Pool.GameObjectPool.ReleasePool(item.Value.AssetFullPath);
                    item.Value.Release();
                    m_RemoveUnloadAssetList.Add(item.Key);
                }
            }

            //字典中移除 被释放的资源引用
            foreach (var item in m_RemoveUnloadAssetList)
                m_AssetRefEntityDic.Remove(item);

            m_RemoveUnloadAssetList.Clear();
        }

        /// <summary>
        /// 获取已经加载好的 assetRefEntity
        /// </summary>
        /// <param name="assetFullPath"></param>
        /// <returns></returns>
        public AssetRefEntity GetExitAssetRefEntity(string assetFullPath)
        {
            foreach (var item in m_AssetRefEntityDic)
            {
                if (item.Value.AssetFullPath == assetFullPath)
                {
                    return item.Value;
                }
            }
            return null;
        }

        public void Dispose()
        {
            m_AssetRefEntityDic.Clear();
            m_AssetRefEntityDic = null;
            m_RemoveUnloadAssetList.Clear();
            m_RemoveUnloadAssetList = null;
        }
    }
}